package us.icitap.cm.business.entities;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import javax.persistence.TableGenerator;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;

import org.eclipse.persistence.annotations.Customizer;

import us.icitap.cm.utils.MyCustomizer;


@Entity
@Customizer(MyCustomizer.class)
@Table(name="APP_ENTITY",schema="MPC")
//@SequenceGenerator(name="APP_ENTITY_SEQ", schema="MPC", initialValue=1, allocationSize=1)
@TableGenerator(name="APP_ENTITY_IDS",table="AUTO_IDS",valueColumnName="LAST_ID",initialValue=1, allocationSize=1,schema="MPC")
public class AppEntity implements Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = 2512742024476243628L;

	@Id
//	@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="APP_ENTITY_SEQ")
	@GeneratedValue(strategy=GenerationType.TABLE,generator="APP_ENTITY_IDS")
	private Integer id;

	@Enumerated(EnumType.STRING)
	@Column(name="ENTITY_TYPE")
	private EntityTypeEnum entityType;
	
	
	
	@OneToOne(mappedBy="appEntity")
	private Place place;
	
	
	@OneToOne(mappedBy="appEntity",cascade=CascadeType.ALL)
	@JoinColumn()
	private Person person;
	
	@OneToOne(mappedBy="appEntity")
	@JoinColumn()
	private Vehicle vehicle;
	
	@OneToOne(mappedBy="appEntity")
	@JoinColumn
	private Drug drug;
	
	@OneToOne(mappedBy="appEntity")
	@JoinColumn
	private Item item;
	
	@OneToOne(mappedBy="appEntity")
	@JoinColumn
	private CaseOfficer caseOfficer;
	
	@OneToOne(mappedBy="appEntity")
	@JoinColumn
	private Organization organization;
	
	@OneToOne(mappedBy="appEntity")
	@JoinColumn
	private Weapon weapon;
	
	@OneToOne(mappedBy="appEntity")
	@JoinColumn
	private Document document;
	
	@OneToOne(mappedBy="appEntity")
	@JoinColumn
	private Control control;
	
	@OneToOne(mappedBy="appEntity")
	@JoinColumn
	private Experiment experiment;
	
	@OneToOne(mappedBy="appEntity")
	@JoinColumn
	private Expertise expertise;
	
	@ManyToOne
	@JoinColumn(name="EVIDENCE_ID")
	private Evidence evidence;
	

	@Column(name="RECORD_USER",length=60)
	private String recordUser;
	
	@Temporal(TemporalType.TIMESTAMP)
	@Column(name="RECORD_DATE")
	private Date recordDate;

	@ManyToOne
	@JoinColumn(name="HISTORY_APP_ENTITY_ID")
	private AppEntity historyAppEntity;
	
	@Transient
	private boolean newRecord = false;
	

	@OneToMany(mappedBy="entityOne")
	private List<EntityEntityAssociation> entityAssocAsOneList;
	
	@OneToMany(mappedBy="entityOne")
	private List<EntityEntityAssociation> entityAssocAsTwoList;
	
	
	
	
	
	public AppEntity() {
		super();
	}

	public AppEntity(String recordUser, EntityTypeEnum entityTypeEnum) {
		super();
		
		this.recordUser = recordUser;
		this.entityType = entityTypeEnum;
		this.setNewRecord(true);
		
		switch(this.entityType){
		
		case PLACE: 		this.place = new Place(); this.place.setAppEntity(this); break;
		case PERSON: 		this.person = new Person();this.person.setAppEntity(this); break;
		case DOCUMENT: 		this.document = new Document(); this.document.setAppEntity(this); break;	
		case VEHICLE: 		this.vehicle = new Vehicle(); this.vehicle.setAppEntity(this); break;
		case DRUG: 			this.drug = new Drug(); this.drug.setAppEntity(this); break;
		case WEAPON: 		this.weapon = new Weapon(); this.weapon.setAppEntity(this); break;
		case ITEM: 			this.item = new Item(); this.item.setAppEntity(this); break;
		case ORGANIZATION: 	this.organization = new Organization(); this.organization.setAppEntity(this); break;
		case OFFICER: 		this.caseOfficer = new CaseOfficer(); this.caseOfficer.setAppEntity(this); break;
		case CONTROL: 		this.control = new Control(); this.control.setAppEntity(this); break;	
		case EXPERIMENT: 	this.experiment = new Experiment(); this.experiment.setAppEntity(this); break;
		case EXPERTISE: 	this.expertise = new Expertise(); this.expertise.setAppEntity(this); break;
			default :		break;
		
		}
	}


	public AppEntity(AppEntity appEntity) {
		super();
		
	
		this.entityType = appEntity.getEntityType();
		this.setNewRecord(appEntity.isNewRecord());
		
		this.setHistoryAppEntity(appEntity);
		
		if(appEntity.getCaseOfficer() != null){
			this.caseOfficer = new CaseOfficer(appEntity.getCaseOfficer());
			this.caseOfficer.setAppEntity(this);
		}
		if(appEntity.getDocument() != null){
			this.document = new Document(appEntity.getDocument());
			this.document.setAppEntity(this);
		}
		
		if(appEntity.getDrug() != null){
			this.drug = new Drug(appEntity.getDrug());
			this.drug.setAppEntity(this);
		}
		
		if(appEntity.getItem()!= null){
			this.item = new Item(appEntity.getItem());
			this.item.setAppEntity(this);
		}
		
		if(appEntity.getOrganization()!= null){
			this.organization = new Organization(appEntity.getOrganization());
			this.organization.setAppEntity(this);
		}
		
		if(appEntity.getPerson()!= null){
			this.person = new Person(appEntity.getPerson());
			this.person.setAppEntity(this);
		}
		
		if(appEntity.getPlace()!= null){
			this.place = new Place(appEntity.getPlace());
			this.place.setAppEntity(this);
		}
		
		if(appEntity.getVehicle()!= null){
			this.vehicle = new Vehicle(appEntity.getVehicle());
			this.vehicle.setAppEntity(this);
		}
		
		if(appEntity.getWeapon()!= null){
			this.weapon = new Weapon(appEntity.getWeapon());
			this.weapon.setAppEntity(this);
		}

		if(appEntity.getEvidence() != null){
			this.evidence = new Evidence(appEntity.getEvidence());
			
		}
		
		if(appEntity.getControl() != null){
			this.control = new Control(appEntity.getControl());
			this.control.setAppEntity(this);
		}
		
		if(appEntity.getExperiment() != null){
			this.experiment = new Experiment(appEntity.getExperiment());
			this.experiment.setAppEntity(this);
		}
		
		if(appEntity.getExpertise() != null){
			this.expertise = new Expertise(appEntity.getExpertise());
			this.expertise.setAppEntity(this);
		}
		
		
	}
	
	public void addEntityAssocAsOne(EntityEntityAssociation eea){
		if(this.entityAssocAsOneList == null) entityAssocAsOneList = new ArrayList<EntityEntityAssociation>();
		entityAssocAsOneList.add(eea);
	}
	
	public void addEntityAssocAsTwo(EntityEntityAssociation eea){
		if(this.entityAssocAsTwoList == null) entityAssocAsTwoList = new ArrayList<EntityEntityAssociation>();
		entityAssocAsTwoList.add(eea);
	}
	

	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
		switch(this.entityType){
			case PLACE: place.setId(null); break;
			case PERSON: if(person != null) person.setId(null); break;
			case VEHICLE: vehicle.setId(null); break;
			case DRUG: drug.setId(null); break;
			case WEAPON: weapon.setId(null); break;
			case ITEM: item.setId(null); break;
			case DOCUMENT: document.setId(null); break;
			case ORGANIZATION: organization.setId(null); break;
			case OFFICER: caseOfficer.setId(null); break;
			case CONTROL: control.setId(null); break;
			case EXPERIMENT: experiment.setId(null); break;
			case EXPERTISE: expertise.setId(null); break;
			default : break;
		}
		
	}

	
	public boolean hasAssociationTypeAsBeingOne(String assoc){
		if(this.entityAssocAsOneList == null) return false;
		for (EntityEntityAssociation eea : this.entityAssocAsOneList) {
			if(assoc.equals(eea.getAssociationType().getTag())){
				return true;
			}
		}
		return false;
	}
	
	public EntityTypeEnum getEntityType() {
		return entityType;
	}

	public void setEntityType(EntityTypeEnum entityType) {
		this.entityType = entityType;
	}

	public Person getPerson() {
		return person;
	}

	public void setPerson(Person person) {
		this.person = person;
	}

	public Vehicle getVehicle() {
		return vehicle;
	}

	public void setVehicle(Vehicle vehicle) {
		this.vehicle = vehicle;
	}

	public String getRecordUser() {
		return recordUser;
	}

	public void setRecordUser(String recordUser) {
		this.recordUser = recordUser;
	}

	public Date getRecordDate() {
		return recordDate;
	}

	public void setRecordDate(Date recordDate) {
		this.recordDate = recordDate;
	}


	@Override
	public String toString() {
		
		if(EntityTypeEnum.PLACE.equals(this.entityType)) return  this.getPlace().toString();
		if(EntityTypeEnum.PERSON.equals(this.entityType)) return this.getPerson().toString();
		if(EntityTypeEnum.VEHICLE.equals(this.entityType)) return this.getVehicle().toString();
		if(EntityTypeEnum.DRUG.equals(this.entityType)) return this.getDrug().toString();
		if(EntityTypeEnum.WEAPON.equals(this.entityType)) return this.getWeapon().toString();
		if(EntityTypeEnum.ITEM.equals(this.entityType)) return this.getItem().toString();
		if(EntityTypeEnum.DOCUMENT.equals(this.entityType)) return this.getDocument().toString();
		if(EntityTypeEnum.ORGANIZATION.equals(this.entityType)) return this.getOrganization().toString();
		if(EntityTypeEnum.OFFICER.equals(this.entityType)) return this.getCaseOfficer().toString();
		if(EntityTypeEnum.CONTROL.equals(this.entityType)) return this.getControl().toString();
		if(EntityTypeEnum.EXPERIMENT.equals(this.entityType)) return this.getExperiment().toString();
		if(EntityTypeEnum.EXPERTISE.equals(this.entityType)) return this.getExpertise().toString();
		return null;
	}

	public String getAlternativeString(){
		
		if(EntityTypeEnum.PLACE.equals(this.entityType)) return "Adrese/Objekt: " +  this.getPlace().toString();
		if(EntityTypeEnum.PERSON.equals(this.entityType)) return "Person: " + this.getPerson().toString();
		if(EntityTypeEnum.VEHICLE.equals(this.entityType)) return "Automjet: " + this.getVehicle().toString();
		if(EntityTypeEnum.DRUG.equals(this.entityType)) return "Droge: " + this.getDrug().toString();
		if(EntityTypeEnum.WEAPON.equals(this.entityType)) return "Arme: " + this.getWeapon().toString();
		if(EntityTypeEnum.ITEM.equals(this.entityType)) return "Artikull/Send: " + this.getItem().toString();
		if(EntityTypeEnum.DOCUMENT.equals(this.entityType)) return "Dokument: " +  this.getDocument().toString();
		if(EntityTypeEnum.ORGANIZATION.equals(this.entityType)) return "Organizate: " + this.getOrganization().toString();
		if(EntityTypeEnum.OFFICER.equals(this.entityType)) return "Oficer: " + this.getCaseOfficer().toString();
		if(EntityTypeEnum.CONTROL.equals(this.entityType)) return "Kontroll: " + this.getControl().toString();
		if(EntityTypeEnum.EXPERIMENT.equals(this.entityType)) return this.getExperiment().toString();
		if(EntityTypeEnum.EXPERTISE.equals(this.entityType)) return this.getExpertise().toString();
		return null;
	}
	
	public Document getDocument() {
		return document;
	}

	public void setDocument(Document document) {
		this.document = document;
	}

	public boolean isNewRecord() {
		return newRecord;
	}

	public void setNewRecord(boolean newRecord) {
		this.newRecord = newRecord;
	}

	public Place getPlace() {
		return place;
	}

	public void setPlace(Place place) {
		this.place = place;
	}

	public Drug getDrug() {
		return drug;
	}

	public void setDrug(Drug drug) {
		this.drug = drug;
	}

	public Item getItem() {
		return item;
	}

	public void setItem(Item item) {
		this.item = item;
	}

	public CaseOfficer getCaseOfficer() {
		return caseOfficer;
	}

	public void setCaseOfficer(CaseOfficer caseOfficer) {
		this.caseOfficer = caseOfficer;
	}

	public Organization getOrganization() {
		return organization;
	}

	public void setOrganization(Organization organization) {
		this.organization = organization;
	}

	public Weapon getWeapon() {
		return weapon;
	}

	public void setWeapon(Weapon weapon) {
		this.weapon = weapon;
	}



	public AppEntity getHistoryAppEntity() {
		return historyAppEntity;
	}

	public void setHistoryAppEntity(AppEntity historyAppEntity) {
		this.historyAppEntity = historyAppEntity;
	}



	

	
	


	public boolean myEquals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		AppEntity other = (AppEntity) obj;
		if (caseOfficer == null) {
			if (other.caseOfficer != null)
				return false;
		} else if (!caseOfficer.myEquals(other.caseOfficer))
			return false;
		if (document == null) {
			if (other.document != null)
				return false;
		} else if (!document.myEquals(other.document))
			return false;
		if (drug == null) {
			if (other.drug != null)
				return false;
		} else if (!drug.myEquals(other.drug))
			return false;
		if (entityType != other.entityType)
			return false;
	
		if (item == null) {
			if (other.item != null)
				return false;
		} else if (!item.equals(other.item))
			return false;
		if (organization == null) {
			if (other.organization != null)
				return false;
		} else if (!organization.myEquals(other.organization))
			return false;
		if (person == null) {
			if (other.person != null)
				return false;
		} else if (!person.myEquals(other.person))
			return false;
		if (place == null) {
			if (other.place != null)
				return false;
		} else if (!place.myEquals(other.place))
			return false;

		if (vehicle == null) {
			if (other.vehicle != null)
				return false;
		} else if (!vehicle.myEquals(other.vehicle))
			return false;
		if (weapon == null) {
			if (other.weapon != null)
				return false;
		} else if (!weapon.myEquals(other.weapon))
			return false;
		if (evidence == null) {
			if (other.evidence != null)
				return false;
		} else if (!evidence.myEquals(other.evidence))
			return false;
		if (control == null) {
			if (other.control != null)
				return false;
		} else if (!control.myEquals(other.control))
			return false;
		
		if (experiment == null) {
			if (other.experiment != null)
				return false;
		} else if (!experiment.myEquals(other.experiment))
			return false;
		
		if (expertise == null) {
			if (other.expertise != null)
				return false;
		} else if (!expertise.myEquals(other.expertise))
			return false;
		
//		if(this.reportAssociationList == null){
//			if(other.reportAssociationList != null)
//				return false;
//		}
//		else{
//			if(other.reportAssociationList == null)
//				return false;
//			else if(this.reportAssociationList.size() != other.reportAssociationList.size())
//				return false;
//			else{
//				for (EntityReportAssociation era : this.reportAssociationList) {
//					boolean isInside = false;
//					for(EntityReportAssociation eraOther : other.reportAssociationList){
//						if(era.myEquals(eraOther)){
//							isInside = true;
//							break;
//						}
//					}
//					if(!isInside) return false;
//				}
//				
//				for (EntityReportAssociation eraOther : other.reportAssociationList) {
//					boolean isInside = false;
//					for(EntityReportAssociation era : this.reportAssociationList){
//						if(eraOther.myEquals(era)){
//							isInside = true;
//							break;
//						}
//					}
//					if(!isInside) return false;
//				}
//				
//			}
//		}
		
		
		
		return true;
	}


	public List<EntityEntityAssociation> getEntityAssocAsOneList() {
		return entityAssocAsOneList;
	}

	public void setEntityAssocAsOneList(
			List<EntityEntityAssociation> entityAssocAsOneList) {
		this.entityAssocAsOneList = entityAssocAsOneList;
	}

	public List<EntityEntityAssociation> getEntityAssocAsTwoList() {
		return entityAssocAsTwoList;
	}

	public void setEntityAssocAsTwoList(
			List<EntityEntityAssociation> entityAssocAsTwoList) {
		this.entityAssocAsTwoList = entityAssocAsTwoList;
	}



	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result
				+ ((caseOfficer == null) ? 0 : caseOfficer.hashCode());
		result = prime * result
				+ ((document == null) ? 0 : document.hashCode());
		result = prime * result + ((drug == null) ? 0 : drug.hashCode());
		result = prime
				* result
				+ ((entityAssocAsOneList == null) ? 0 : entityAssocAsOneList
						.hashCode());
		result = prime
				* result
				+ ((entityAssocAsTwoList == null) ? 0 : entityAssocAsTwoList
						.hashCode());
		result = prime * result
				+ ((entityType == null) ? 0 : entityType.hashCode());
	
		result = prime
				* result
				+ ((historyAppEntity == null) ? 0 : historyAppEntity.hashCode());
		result = prime * result + ((id == null) ? 0 : id.hashCode());
		result = prime * result + ((item == null) ? 0 : item.hashCode());
		result = prime * result + (newRecord ? 1231 : 1237);
		result = prime * result
				+ ((organization == null) ? 0 : organization.hashCode());
		result = prime * result + ((person == null) ? 0 : person.hashCode());
		result = prime * result + ((place == null) ? 0 : place.hashCode());
		result = prime * result
				+ ((recordDate == null) ? 0 : recordDate.hashCode());
		result = prime * result
				+ ((recordUser == null) ? 0 : recordUser.hashCode());
		result = prime * result
				+ ((evidence == null) ? 0 : evidence.hashCode());
		result = prime * result
				+ ((control == null) ? 0 : control.hashCode());
		
		result = prime * result + ((vehicle == null) ? 0 : vehicle.hashCode());
		result = prime * result + ((experiment == null) ? 0 : experiment.hashCode());
		result = prime * result + ((expertise == null) ? 0 : expertise.hashCode());
		result = prime * result + ((weapon == null) ? 0 : weapon.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		AppEntity other = (AppEntity) obj;
		if (caseOfficer == null) {
			if (other.caseOfficer != null)
				return false;
		} else if (!caseOfficer.equals(other.caseOfficer))
			return false;
		if (document == null) {
			if (other.document != null)
				return false;
		} else if (!document.equals(other.document))
			return false;
		if (drug == null) {
			if (other.drug != null)
				return false;
		} else if (!drug.equals(other.drug))
			return false;
		if (entityAssocAsOneList == null) {
			if (other.entityAssocAsOneList != null)
				return false;
		} else if (!entityAssocAsOneList.equals(other.entityAssocAsOneList))
			return false;
		if (entityAssocAsTwoList == null) {
			if (other.entityAssocAsTwoList != null)
				return false;
		} else if (!entityAssocAsTwoList.equals(other.entityAssocAsTwoList))
			return false;
		if (entityType != other.entityType)
			return false;
		
		if (historyAppEntity == null) {
			if (other.historyAppEntity != null)
				return false;
		} else if (!historyAppEntity.equals(other.historyAppEntity))
			return false;
		if (id == null) {
			if (other.id != null)
				return false;
		} else if (!id.equals(other.id))
			return false;
		if (item == null) {
			if (other.item != null)
				return false;
		} else if (!item.equals(other.item))
			return false;
		if (newRecord != other.newRecord)
			return false;
		if (organization == null) {
			if (other.organization != null)
				return false;
		} else if (!organization.equals(other.organization))
			return false;
		if (person == null) {
			if (other.person != null)
				return false;
		} else if (!person.equals(other.person))
			return false;
		if (place == null) {
			if (other.place != null)
				return false;
		} else if (!place.equals(other.place))
			return false;
		if (recordDate == null) {
			if (other.recordDate != null)
				return false;
		} else if (!recordDate.equals(other.recordDate))
			return false;
		if (recordUser == null) {
			if (other.recordUser != null)
				return false;
		} else if (!recordUser.equals(other.recordUser))
			return false;
		if (evidence == null) {
			if (other.evidence != null)
				return false;
		} else if (!evidence.equals(other.evidence))
			return false;

		if (vehicle == null) {
			if (other.vehicle != null)
				return false;
		} else if (!vehicle.equals(other.vehicle))
			return false;
		if (weapon == null) {
			if (other.weapon != null)
				return false;
		} else if (!weapon.equals(other.weapon))
			return false;
		
		if (control == null) {
			if (other.control != null)
				return false;
		} else if (!control.myEquals(other.control))
			return false;
		
		if (experiment == null) {
			if (other.experiment != null)
				return false;
		} else if (!experiment.myEquals(other.experiment))
			return false;
		
		if (expertise == null) {
			if (other.expertise != null)
				return false;
		} else if (!expertise.myEquals(other.expertise))
			return false;
		
		return true;
	}

	public Evidence getEvidence() {
		return evidence;
	}

	public void setEvidence(Evidence evidence) {
		this.evidence = evidence;
	}

	public Control getControl() {
		return control;
	}

	public void setControl(Control control) {
		this.control = control;
	}

	public Experiment getExperiment() {
		return experiment;
	}

	public void setExperiment(Experiment experiment) {
		this.experiment = experiment;
	}

	public Expertise getExpertise() {
		return expertise;
	}

	public void setExpertise(Expertise expertise) {
		this.expertise = expertise;
	}

	public String toFullString(){
		return "["+ this.getEntityType().getCaption() +"] " + this.toString(); 
	}

}
